package com.xbongbong.parent.abstracts;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.service.impl.FormDataLinkDataUpdateGetServiceImpl;
import com.xbongbong.paas.pojo.dto.FormDataUpdateGetDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.vo.FormDataUpdateGetVO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.help.CommonPermissionHelp;
import com.xbongbong.parent.interfaces.BusinessEditPageRenderService;
import com.xbongbong.parent.parse.data.FormDataUpdateGetAnalysisDataHelp;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.lowcode.ButtonTypeEnum;
import com.xbongbong.pro.formdata.pojo.SaasSpecialParamPojo;
import com.xbongbong.pro.formdata.pojo.dto.FormDataDetailDTO;
import com.xbongbong.pro.formexplain.pojo.vo.HandlerExplainVO;
import com.xbongbong.pro.lowcodeconfig.pojo.dto.LowCodeConfigGetDTO;
import com.xbongbong.pro.lowcodeconfig.pojo.vo.LowCodeConfigGetVO;
import com.xbongbong.pro.permission.pojo.dto.VerifyUpdatePermissionDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.ProPermissionHelp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2022/01/24 15:15
 */
@Component
public abstract class AbstractEditPageRenderService<F, D> implements BusinessEditPageRenderService<F, D> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractEditPageRenderService.class);


    @Resource
    private CommonHelp commonHelp;
    @Resource
    private FormDataUpdateGetAnalysisDataHelp formDataUpdateGetAnalysisDataHelp;
    @Resource
    private FormDataLinkDataUpdateGetServiceImpl formDataLinkDataUpdateGetService;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private CommonPermissionHelp commonPermissionHelp;


    @Override
    public FormDataUpdateGetVO updateGet(FormDataUpdateGetDTO formDataUpdateGetDTO) throws XbbException {
        try {
            FormDataUpdateGetVO formDataUpdateGetVO = new FormDataUpdateGetVO();
            // 校验编辑权限
            validateEditPermission(formDataUpdateGetDTO);
            Integer businessType = formDataUpdateGetDTO.getBusinessType();
            Long dataId = formDataUpdateGetDTO.getDataId();
            // 获取表单实体
            F formEntity = getForm(formDataUpdateGetDTO);

            if (Objects.equals(formDataUpdateGetDTO.getIsOuterLink(), BasicConstant.ONE)) {
                // 外链分享页编辑按钮跳转到系统编辑页面需要传这个参数
                SaasSpecialParamPojo saasSpecialParamPojo = formDataUpdateGetDTO.getSaasSpecialParamPojo();
                if (Objects.isNull(saasSpecialParamPojo)) {
                    saasSpecialParamPojo = new SaasSpecialParamPojo();
                }
                saasSpecialParamPojo.setFromEdit(BasicConstant.ONE);
                formDataUpdateGetDTO.setSaasSpecialParamPojo(saasSpecialParamPojo);
            }
            //先获取data数据
            String corpid = formDataUpdateGetDTO.getCorpid();
            D formData = getData(formDataUpdateGetDTO);
            // 获取低代码配置
            LowCodeConfigGetDTO lowCodeConfigGetDTO = new LowCodeConfigGetDTO();
            lowCodeConfigGetDTO.setCorpid(corpid);
            lowCodeConfigGetDTO.setFormId(formDataUpdateGetDTO.getFormId());
            lowCodeConfigGetDTO.setBusinessType(businessType);
            lowCodeConfigGetDTO.setLoginUser(formDataUpdateGetDTO.getLoginUser());
            lowCodeConfigGetDTO.setType(ButtonTypeEnum.EDIT.getCode());
            LowCodeConfigGetVO lowCodeConfig = getLowCodeConfig(lowCodeConfigGetDTO);
            formDataUpdateGetVO.setLowCodeConfig(lowCodeConfig);
            // 校验审批通过后是否允许编辑
            isApprovedEdit(formDataUpdateGetDTO, formData, formEntity);
            List<FieldAttrEntity> explainList = getExplain(formEntity, corpid);
            PaasFormDataEntityExt paasFormDataEntityExt = (PaasFormDataEntityExt) formData;
            //校验数据权限(团队权限&共享权限)
            validateDataEditPermission(formDataUpdateGetDTO, explainList, paasFormDataEntityExt);
            // ---- 获取用户和部门容器start
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(formDataUpdateGetDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            UserAndDepartmentGetVO userAndDepartmentGetVO = commonHelp.getUserDepartmentMap(userAndDepartmentGetDTO, BasicConstant.ZERO);
            Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
            Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
            // 字段解释通用处理
            HandlerExplainVO handlerExplainVO = handleExplain(formDataUpdateGetDTO, userMap, formData, explainList, formEntity);
            handlerExplainVO.setDepartmentMap(departmentMap);
            handlerExplainVO.setUserMap(userMap);
            explainList = handlerExplainVO.getHeadList();
            // 解析数据
            formatData(formDataUpdateGetDTO, handlerExplainVO, formData);


            formDataUpdateGetVO.setExplainList(explainList);
            // 返回数据封装
            formatSaasAttrToReturn(formDataUpdateGetDTO, formDataUpdateGetVO, formEntity, formData);
            String value = formConfigModel.getConfigValueByRedis(RedisPrefixConstant.ASSIGNMENT_RULES, corpid, formDataUpdateGetDTO.getFormId(), formDataUpdateGetDTO.getSaasMark(), formDataUpdateGetDTO.getBusinessType(), "0");
            if (StringUtil.isNotEmpty(value)) {
                formDataUpdateGetVO.setAssignmentRules(Integer.valueOf(value));
            }
            return formDataUpdateGetVO;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e){
            LOGGER.error("com.xbongbong.parent.service.abstracts.AbstractEditPageRenderService.updateGet error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

    }

    /**
     * 校验数据编辑权限(团队权限&共享权限)
     *
     * @param formDataUpdateGetDTO
     * @param explainList
     * @param paasFormDataEntityExt
     * @throws XbbException
     */
    protected void validateDataEditPermission(FormDataUpdateGetDTO formDataUpdateGetDTO, List<FieldAttrEntity> explainList, PaasFormDataEntityExt paasFormDataEntityExt) throws XbbException{
        if (formDataUpdateGetDTO.getIsCopy()){
            return;
        }
        FormDataDetailDTO formDataDetailDTO = new FormDataDetailDTO();
        BeanUtil.copyProperties(formDataUpdateGetDTO, formDataDetailDTO);
        formDataDetailDTO.setDataCreatorId(paasFormDataEntityExt.getCreatorId());
        VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO(formDataDetailDTO.getLoginUser(), paasFormDataEntityExt);
        boolean hasDataPermission = commonPermissionHelp.checkEditPermission(formDataDetailDTO, verifyUpdatePermissionDTO, ExplainUtil.getExplainMapByList(explainList));
        if (!hasDataPermission){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100050, SystemErrorCodeEnum.API_ERROR_100050.getMsg(), I18nMessageUtil.getMessage(CommonConstant.EDIT));
        }
        commonPermissionHelp.removeConvertedData(paasFormDataEntityExt.getData());
    }

    @Override
    public void validateEditPermission(FormDataUpdateGetDTO formDataUpdateGetDTO) throws XbbException {
        if (formDataUpdateGetDTO.getSaasSpecialParamPojo() != null && Objects.equals(formDataUpdateGetDTO.getSaasSpecialParamPojo().getFromCopy(), BasicConstant.ONE)) {
            //复制跳过编辑权限校验
            return;
        }
        VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO();
        BeanUtil.copyProperties(formDataUpdateGetDTO, verifyUpdatePermissionDTO);
        ProPermissionHelp.verifyEditPermission(verifyUpdatePermissionDTO);
    }

    public ParseSingleRowDataVO parseSingleRowData(FormDataUpdateGetDTO formDataUpdateGetDTO, JSONObject data, Map<String, FieldAttrEntity> explainMap, Map<String, UserEntity> userMap, Map<String, DepartmentEntity> departmentMap) throws XbbException{
        // 解析数据信息
        ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
        BeanUtil.copyProperties(formDataUpdateGetDTO, parseSingleRowDataDTO);
        parseSingleRowDataDTO.setUserMap(userMap);
        parseSingleRowDataDTO.setDataJsonObject(data);
        parseSingleRowDataDTO.setExplainMap(explainMap);
        parseSingleRowDataDTO.setDepartmentMap(departmentMap);
        ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
        LinkResultDataVO linkResultDataVO = parseSingleRowDataVO.getLinkResultDataVO();
        JSONObject result = parseSingleRowDataVO.getResult();
        // 获取关联数据的信息
        if ( linkResultDataVO != null && !linkResultDataVO.getLinkData().isEmpty() && !linkResultDataVO.getLinkDataSet().isEmpty() ) {
            linkResultDataVO.setData(result);
            linkResultDataVO.setExplainMap(explainMap);
            linkResultDataVO.setUserMap(userMap);
            linkResultDataVO.setDepartmentMap(departmentMap);
            List<FieldAttrEntity> explainList = new ArrayList<>(explainMap.values());
            linkResultDataVO.setExplainList(explainList);
            result = formDataLinkDataUpdateGetService.formDataLinkDataGet(formDataUpdateGetDTO, linkResultDataVO);
            parseSingleRowDataVO.setResult(result);
        }
        return parseSingleRowDataVO;
    }
}
